/** \file gu_render_context.cpp */

#include "gu_render_context.h"
#include "gu_shader_parser.h"

#include <GL/glew.h>

#include<algorithm>
#include<cassert>

namespace gu {
namespace state {


static void clearColor(gr::Float4& f4)
{
    glClearColor(f4.x, f4.y, f4.z, 1.0f);
}
static void clearDepth(float f)
{
    glClearDepthf(f);
}

static GLboolean boolToGl(bool mask){return mask ? GL_TRUE:GL_FALSE;}

static void colorMask(bool mask)
{
    auto val = boolToGl(mask);
    glColorMask(val, val, val, val);
}

static void depthMask(bool mask)
{
    auto val = boolToGl(mask);
    glDepthMask(val);
}

static void enable(GLenum cap)
{
    glEnable(cap);
}

static void disable(GLenum cap)
{
    glDisable(cap);
}

void apply_glsl330(DataSequence& data)
{
    GLbitfield clearBits = 0;

    data.sort([](Data& a, Data& b)->bool{return a.type < b.type;});

    for(auto d = data.begin(); d != data.end(); ++d)
    {
#define CASE(state_, fun_) case state_: fun_; break
        switch(d->type)
        {
            CASE(SET_CLEAR_COLOR,     clearColor(d->f4));
            CASE(SET_CLEAR_DEPTH,     clearDepth(d->f));
            CASE(DISABLE_COLOR_WRITE, colorMask(false));
            CASE(DISABLE_DEPTH_WRITE, depthMask(false));
            CASE(DISABLE_DEPTH_TEST,  disable(GL_DEPTH_TEST));

            CASE(ENABLE_COLOR_WRITE, colorMask(true));
            CASE(ENABLE_DEPTH_WRITE, depthMask(true));
            CASE(ENABLE_DEPTH_TEST,  enable(GL_DEPTH_TEST));

            CASE(CLEAR_COLOR_BUFFER, clearBits |= GL_COLOR_BUFFER_BIT);
            CASE(CLEAR_DEPTH_BUFFER, clearBits |= GL_DEPTH_BUFFER_BIT);

            default:
            {
                assert(!"Type error");
                break;
            }
        }
#undef CASE
    }

    if(clearBits)
    {
        glClear(clearBits);
    }

}

} // state
} // gu

